package sdk3.components.remoteService
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Label;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	
	import sdk3.components.remoteService.LoginEvent;
	import sdk3.components.remoteService.RegisterEvent;
	import sdk3.components.remoteService.connectionParameters;
	import sdk3.components.remoteService.remoteService_java;
	import sdk3.components.remoteService.remoteService_utility;
	import sdk3.components.remoteService.user;
	
	import singleton.singleton_storage;
	
	public class remoteService_java extends remoteService_utility
	{
		/**
		 * Software: remoteService_java												
		 * Version:  1.1
		 * Date:     2010_06_21_TIME_17:25:24
		 * Author:    
		 * 	  * LICENSE:  GNU General Public License (http://www.gnu.org/licenses/gpl.html) 	 *  	 * English: 		This program is free software; 		you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; 		either version 3 of the License, or (at your option) any later version.   		This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 		without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 		See the GNU General Public License for more details. 		You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.   		 * Excerpt English: 		 * Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), 		 * that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things   		Auf Deutsch: 		Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, 		weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version. 		Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 		sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. 		Details finden Sie in der GNU General Public License. 		Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben. 		Falls nicht, siehe <http://www.gnu.org/licenses/>.   		 * Auszug Deutsch: 		 * Wenn wir von freier Software sprechen, so beziehen wir uns auf Freiheit, nicht auf den Preis. 		 * Unsere Allgemeinen Öffentlichen Lizenzen sind darauf angelegt, sicherzustellen, daß Sie die Freiheit haben, 		 * Kopien freier Software zu verbreiten (und dafür etwas zu berechnen, wenn Sie möchten), die Möglichkeit, 		 * daß Sie die Software als Quelltext erhalten oder den Quelltext auf Wunsch bekommen, daß Sie die Software 		 * ändern oder Teile davon in neuen freien Programmen verwenden dürfen und daß Sie wissen, daß Sie dies alles tun dürfen.   GNU General Public License (http://www.gnu.org/licenses/gpl.html) 	 *  	 * English: 		This program is free software; 		you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; 		either version 3 of the License, or (at your option) any later version.   		This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 		without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 		See the GNU General Public License for more details. 		You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.   		 * Excerpt English: 		 * Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), 		 * that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things   		Auf Deutsch: 		Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, 		weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version. 		Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 		sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. 		Details finden Sie in der GNU General Public License. 		Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben. 		Falls nicht, siehe <http://www.gnu.org/licenses/>.   		 * Auszug Deutsch: 		 * Wenn wir von freier Software sprechen, so beziehen wir uns auf Freiheit, nicht auf den Preis. 		 * Unsere Allgemeinen Öffentlichen Lizenzen sind darauf angelegt, sicherzustellen, daß Sie die Freiheit haben, 		 * Kopien freier Software zu verbreiten (und dafür etwas zu berechnen, wenn Sie möchten), die Möglichkeit, 		 * daß Sie die Software als Quelltext erhalten oder den Quelltext auf Wunsch bekommen, daß Sie die Software 		 * ändern oder Teile davon in neuen freien Programmen verwenden dürfen und daß Sie wissen, daß Sie dies alles tun dürfen. 
		 * 
		 * WHAT IS IT GOOD FOR?/PURPOSE/MISSION STATEMENT: tries to make communication with an java based backend as easy as possible *
		 * 
			xml tends to be "slow" but still faster than amfphp and probably faster than zendamf because of the slow way of packing amf packets via php on the server side.
			
			xml packets can become compressed/ziped anyway by tomcat.
			
		 * SECURITY NOTE:
			there is no sdk3 functionality that will let you send & execute sql queries DIRECTLY to the backend.
			all commands are translated into sql-statements in the java BACKEND ONLY! Why is that so?
			
			Because if an attacker knows how your app is sending sql statements
			1. he can just copy & paste one's sql command and substitute the sql-command with something like "drop all database" or "read all database"
			and gets a valid result by the webserver.
			
			2. prevents sql-injection in app-forms
			whatever the user enters (it can be the most wicked and weird sql statement) it will be forwarded as such to the backend and probably do nothing, because it returns an error.

 		* FEATURES OVERVIEW
			 * o xml read, write, delete, update
			 * o SPEED TEST: on Core2Duo, debug version about 1700 mysql entries per second.
			 * o SPEED TEST: on Core2Duo, release-version about 2300 mysql entries per second.
			 * (bottleneck is flashplayers xml decode function, not server side java (php server side used to be bottle neck esp. with bigger data sets))
			 *  
			 * CHANGELOG:
			 * ok READ_TABLE via xml implemented
			 * o READ_TABLE via paging via xml implemented
			 * 
		 * **/
		/** example with paging with definition of loading bar:
		 * 
		 * Example for loading_bar: (one misused buttons for this)
			 <mx:ApplicationControlBar width="300">
			 <mx:HBox id="loading_bar" width="100%" horizontalGap="0">
			 <mx:Button fillColors="{['#ff0000', '#ff0000', '#ff0000', '#ff0000']}" label="LOADING..................." width="100%"/>
			 <mx:Button fillColors="{['#ff0000', '#ff0000', '#ff0000', '#ff0000']}" label=".......................LOADED!" width="0"/>
			 </mx:HBox>
			 </mx:ApplicationControlBar>
		 **/
		/**
 		 * CURRENTLY IMPLEMETED FEATURES / COMMAND SET:
		 * "readTable"
		 	* readTable -> read the whole table and transmit it with one request/response
			 * 
		 * "readTableFiltered"
			 * if you only want to read certain columns and not the whole table (including passwords/usernames)
			 * there also comes data with this request, the data can contain
			 * informations on: what rows/columns should not be transmitted (e.g.
			 * confidental stuff when reading a whole table, e.g. passwords of other
			 * users etc.)
		* "readRange"
		 	* Read only a part of a database-table from ID.... to ID
		 * "count"
		 	* counts how many records are in a given table
		 * "insert"
		 	* write records/data into a table
		 * "insertReturnTable"
		 	* will insert a record into a table and return the all records of the table including the new record
		 * "insertIfNotExists"
		 	* insert data only if the data not already exists in database
		 * "update"
	 	 	* update/change records in a table
		 * "register"
		 	* register a new user 
		 *
		 * "poll"
			 * has many core communication functionalities
			 * 1. return a list of all users
			 * 1.1. report on/offline status of user offline is defined as: no polling since 1minute...
			 * then user is marked "offline" by the system.
			 * 
			 * 2. update user / current session informations: ping, groups, lastlogin, status, loggedIn etc.
			 * 
			 * 3. mark read messages readMessages as read
			 * 
			 * 4. check for new messages and deliver them if they are marked "new" or "offline"
			 * 
			 * 5. save session: status of what windows are open and at what position, what discussion was last chatted about... whith who... etc.
			 * 
			 * 6. determine ping time

  		 * "chat"
		 	 * this function writes one record per message
			 * 
			 * it is not good for chat because for chats its better to have one record per "session"
			 * 
			 * handles the delivery of chat messages
			 * 
			 * how this works:
			 * 
			 * when user A writes to user B a new chat-session-record with a ChatSessionID A:B is written
			 * into table chat
			 * 
			 * in this record the whole chat session is written in this format:
			 * 
			 * userName:chatMessage#
			 * userName:chatMessage#
			 * userName:chatMessage#userName:chatMessage#userName:chatMessage#userName:chatMessage#
			 * 
			 * during polling it is always compared
			 *     how much chat-messages (chat session split by #) of chat are in the database
			 * and how much chat-messages of chat are displayed to the client
			 * 
			 * if the amount of chat-messages in the database is not the amount of chat-messages
			 * displayed to the user than the server automatically answers the poll
			 * with the missing chat messages.
			 * 
			 * thats the plan now lets see how well this works.
			 * 
		* "deliverMessage"
			 * 		 * this function writes one record per message
			 * 
			 * it is not good for chat because for chats its better to have one record per "session"
			 * 
			 * if you want a chat use function "chat" instead
			 * 
			 * handles the delivery of a messages
			 * 
			 * how this works: basically for every user (groups are just
			 * accumulations of users) a record will be written to table
			 * communication.
			 * 
			 * this makes it easy to retrieve all messages for a given user.
			 * 
			 * // get only all messages for toUserID 1
			   SELECT * FROM `communication` * WHERE `toUserID` = 1
			 * 
			 * // get only new messages for toUserID 1
			   SELECT * FROM `communication` WHERE `toUserID` = 1 AND `read` = 0
			 * 
			 * 0. translate groups/discussion subscribers/subdiscussions subscribers
			 * to a list/HashMap of users 1. does the receiver exist? no: don't
			 * write a record yes: 2. is the receiver ignoring the source? yes:
			 * don't write a record no: 3. write a record with receiverUser with the
			 * username of the receiving user.
			 * 
			 * message format: action:deliverMessage data:message/=username:
			 * test/,toGroupID
			 * /=1/,discussionParentID/=0/,fromUserID/=1/,status/=unread
			 * /,timeSend/=1305456522852
			 * /,toUserID/=0/,spam/=0/,subject/=/,toProjectID
			 * /=0/,toDiscussionID/=0/; key_value_delimiter:/=
			 * value_pair_delimiter:/, loginPassword:passwd ID:1
			 * passwordEncryption:clear text value_enclosed_by: data_format:array
			 * first_line_contains_keys:false

 		* "login"
             * login -> check if given username & password are in the given table
             * (default: users)
             *
             * iterates through the list of loaded users & checks if there is a
             * user with the given username and given password sends username +
             * password to server server responds with LOGIN_RESULT = have a
             * nice day! status = login success
             *
             * LOGIN_RESULT = password did not match status = login failed
             *
             * LOGIN_RESULT = user does not exis status = login failed
		 **/
		public var loading_bar:Object = null;
		
		/** some object that displays informations about the data transfer process
		 * needs to have a ["text"] property
		 * **/
		public var STATUS_LABEL:Object = new Label();

		/**
		 * urlToBackend
			read from a config.xml file in the same dir as the *.swf
				-> e.g. http://192.168.0.65:8080/flexBackend/endpoint_xml
			Format is:
		 <?xml version="1.0" encoding="utf-8"?>
			<config>
			   <server host="192.168.0.65" url="http://192.168.0.65:8080/flexBackend/endpoint_xml"/>
			 </config>
		**/
		public var urlToBackend:String = "";
		
		public function remoteService_java(urlToBackend:String = "",STATUS_LABEL:Object = null,loading_bar:Object = null,dataEncoding:String = "xml")
		{
			if(urlToBackend != null)
			{
				this.urlToBackend = urlToBackend;
			}
			if(loading_bar != null)
			{
				this.loading_bar = loading_bar;
			}
			if(STATUS != null)
			{
				this.STATUS_LABEL = STATUS_LABEL;
				this.USER_LABEL_STATUS = STATUS_LABEL;
				this.DEV_LABEL_STATUS = STATUS_LABEL;
			}

			/** depending on the method used, request will be dispatched in different ways. **/
			if(dataEncoding == 'xml')
			{
				if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
				}
				
				if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLFault);
				}
				
				if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
				}
			}
			else if(dataEncoding == 'amf')
			{
				/** amf support due to complicated blazeds setup not implemented yet **/
/*				if(this.hasEventListener('amfResult') == false)
				{
					this.addEventListener('amfResult', onAMFResult);
				}
				if(this.hasEventListener('amfFault') == false)
				{
					this.addEventListener('amfFault', onAMFFault);
				}
*/				/* 				if(this.hasEventListener(ResultEvent.RESULT) == false)
				{
				this.addEventListener(ResultEvent.RESULT, onAMFResult);
				}
				if(this.hasEventListener(FaultEvent.FAULT) == false)
				{
				this.addEventListener(FaultEvent.FAULT, onAMFFault);
				}
				*/				
				/** register event listeners **/
/*				if(responder == null)
				{
					responder = new Responder(onAMFResult,onAMFFault);
				}
				if(connection == null)
				{
					connection = new NetConnection();
				}
*/				
				/**AS2 functionality, NetConnection() -> Creates a NetConnection object that you can use with a NetStream object to invoke commands on a remote application server or to play back streaming video (FLV) files locally or from a server. **/
				// register all kinds of event listeners to NetConnection
/*				if(connection.hasEventListener(AsyncErrorEvent.ASYNC_ERROR) == false)
				{
					connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAMFFault);
				}
				if(connection.hasEventListener(IOErrorEvent.IO_ERROR) == false)
				{
					connection.addEventListener(IOErrorEvent.IO_ERROR, onAMFFault);
				}
				if(connection.hasEventListener(NetStatusEvent.NET_STATUS) == false)
				{
					connection.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
				}
				if(connection.hasEventListener(SecurityErrorEvent.SECURITY_ERROR) == false)
				{
					connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onAMFFault);
				}
*/			}
		}

		/** perform a custom action that must be implemented in the backend to work
		 * the action is defined by a keyword that is asigned to the request-object automatically.
		 * **/
		public function SEND(USER:Object,DATA:Object = null,ACTION:String = "",TableName:String = "",DatabaseName:String = ""):void
		{
			if(c_OBJECT_inst.empty(urlToBackend))
			{
				throw new Error("remoteService_java.as says 'urlToBackend is empty... need an url to the server, otherwise can not send the requests.'");
				return;
			}

			/** send info how the data was serialized **/
			var control_element:Object = new Object();
			var SERIALIZED_DATA:String = '';

			/** if additional data is to be inserted with the user **/
			if(DATA != null)
			{
				SERIALIZED_DATA = RSU.serialize(DATA);
			}

			// asign default values
			control_element['TableName'] = TableName;
			control_element['DatabaseName'] = DatabaseName;
			control_element['data_format'] = 'array';
			control_element['value_pair_delimiter'] = '/,';
			control_element['element_delimiter'] = '/;';
			control_element['key_value_delimiter'] = '/=';
			control_element['first_line_contains_keys'] = 'false';
			control_element['value_enclosed_by'] = '';
			
			rpcResult = new Array();  /** reset result array of this instance **/
			HTTPSERVICE_XML = new HTTPService();

			if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLFault);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
			}
			
			HTTPSERVICE_XML.method = "POST";
			HTTPSERVICE_XML.useProxy = false;
			HTTPSERVICE_XML.resultFormat = 'object'; // xml, array, object

			HTTPSERVICE_XML.request = c_OBJECT_inst.merge(control_element,HTTPSERVICE_XML.request);

			HTTPSERVICE_XML.url = this.urlToBackend;

			HTTPSERVICE_XML.request['action'] = ACTION;
			HTTPSERVICE_XML.request['data'] = SERIALIZED_DATA;
			HTTPSERVICE_XML.request['passwordEncryption'] = mysql_real_escape_string(USER["passwordEncryption"]);
			HTTPSERVICE_XML.request['loginPassword'] = mysql_real_escape_string(USER["password"]);
			HTTPSERVICE_XML.request['loginUser'] = mysql_real_escape_string(USER["username"]);
			HTTPSERVICE_XML.request['ID'] = USER["ID"];

			HTTPSERVICE_XML.send();
		}

		/** read whole table in one chunk **/
		public function XML_READ_TABLE():void
		{
			rpcResult = new Array();  /** reset result array of this instance **/
			HTTPSERVICE_XML = new HTTPService();

			if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLFault);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
			}
			
			HTTPSERVICE_XML.method="POST";
			HTTPSERVICE_XML.useProxy=false;
			HTTPSERVICE_XML.request['action'] = 'readTable';
			HTTPSERVICE_XML.resultFormat = 'object'; // xml, array, object

			HTTPSERVICE_XML.request = singleton_storage.singleton().connectionParameterss.endpoint_to_request(HTTPSERVICE_XML.request);
			
			HTTPSERVICE_XML.url = HTTPSERVICE_XML.request['url'];
			
			HTTPSERVICE_XML.send();
		}

		/** updates elements in given endpoint.TableName **/
		public function UPDATE(elements:Array):void
		{
			rpcResult = new Array();  /** reset result array of this instance **/
			HTTPSERVICE_XML = new HTTPService();

			if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLFault);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
			}
			
			HTTPSERVICE_XML.method="POST";
			HTTPSERVICE_XML.useProxy=false;
			HTTPSERVICE_XML.request['action'] = 'update';
			HTTPSERVICE_XML.request['data'] = elements;
			HTTPSERVICE_XML.resultFormat = 'object'; // xml, array, object

			HTTPSERVICE_XML.request = singleton_storage.singleton().connectionParameterss.endpoint_to_request(HTTPSERVICE_XML.request);
			
			HTTPSERVICE_XML.url = HTTPSERVICE_XML.request['url'];
			
			HTTPSERVICE_XML.send();
		}

		public var RSU:remoteService_utility = new remoteService_utility();
		
		/** INSERTs elements in given singleton_storage.singleton().connectionParameterss.TableName
		 * send data to server as list
		 * DATA
		 * -> basically a array of object that consist of elements. 
		 * every object corresponds to one entry in the database.
		 * key -> values of the object must match the column names in the database.
		 * 
		 * SPECIAL-ELEMENT:
		 * -> to also send some control infos how to process the data to the server an special crafted element the
		 * control_element
		 * 
		 * it can be of any kind of format that the backend understands. (search for if(action.equals("insert")) in the backend)
		 * 
		 * currently implemented key:values, format & functionality:
		 * var control_element:Object = {data_format:'csv',first_line_contains_keys:'true',value_enclosed_by:'"',values_delimiter:',',line_delimiter:';'};
		 * 
		 * property that can be used for different kind of data
		 * control_element['misc'] = 'check if allready exists:username'
		 * 
		 **/
		public function INSERT(DATA:Object,control_element:Object):void
		{
			/** serialize DATA into a stream of text **/
			var SERIALIZED_DATA:String = '';
			
			if(control_element == null)
			{
				//define default control element
				control_element = new Object();
				control_element['data_format'] = 'array'; // 'csv'
				control_element['value_pair_delimiter'] = '/,';
				control_element['element_delimiter'] = '/;';
				control_element['key_value_delimiter'] = '/=';
				control_element['first_line_contains_keys'] = 'false';
				control_element['value_enclosed_by'] = '';
			}

			if(DATA is Array)
			{
				var DATA_ARRAY:Array = DATA as Array;
				SERIALIZED_DATA = RSU.serialize(DATA_ARRAY);
			}
			else if(DATA is String)
			{
				SERIALIZED_DATA = DATA as String;
			}
			else if(DATA is Object)
			{
				SERIALIZED_DATA = RSU.serialize(DATA);
			}

			rpcResult = new Array();  /** reset result array of this instance **/
			HTTPSERVICE_XML = new HTTPService();

			if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLFault);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
			}

			HTTPSERVICE_XML.method="POST";
			HTTPSERVICE_XML.useProxy=false;
			HTTPSERVICE_XML.request['action'] = 'insert';

			HTTPSERVICE_XML.request['data'] = SERIALIZED_DATA;
			HTTPSERVICE_XML.resultFormat = 'object'; // xml, array, object

			HTTPSERVICE_XML.request = singleton_storage.singleton().connectionParameterss.endpoint_to_request(HTTPSERVICE_XML.request);
			HTTPSERVICE_XML.request = c_OBJECT_inst.merge(control_element,HTTPSERVICE_XML.request);
			
			HTTPSERVICE_XML.url = HTTPSERVICE_XML.request['url'];

			HTTPSERVICE_XML.send();
		}

		/** read/stream a table in smal chunks via xml **/
		public function XML_READ_TABLE_WITH_PAGING(loading_bar:Object = null):void
		{
			rpcResult = new Array();  /** reset result array of this instance **/
			
			if(singleton_storage.singleton().connectionParameterss.packet_size == 0)
			{
				OBJECT_PAGING_XML['packet_size'] = singleton_storage.singleton().connectionParameterss.packet_size;
			}
			else
			{
				OBJECT_PAGING_XML['packet_size'] = singleton_storage.singleton().connectionParameterss.packet_size;
			}
			
			// PHASE1
			if(singleton_storage.singleton().connectionParameterss.TableName != null && singleton_storage.singleton().connectionParameterss.DatabaseName != null)
			{
				var ObjectMETA:Object = {TableName:singleton_storage.singleton().connectionParameterss.TableName,DatabaseName:singleton_storage.singleton().connectionParameterss.DatabaseName};
				
				this.loading_bar = OBJECT_PAGING_XML['loading_bar'] = loading_bar;
				
				OBJECT_PAGING_XML['METHOD'] = 'xml';
				
				OBJECT_PAGING_XML = singleton_storage.singleton().connectionParameterss.endpoint_to_request(OBJECT_PAGING_XML);
				
				FUNC_SET_PROGRESS(0,100,OBJECT_PAGING_XML['loading_bar']); /** reset loading bar **/
				
				this.STATUS.text = 'lade Daten...';
				
				OBJECT_PAGING_XML['loop_count_elements_active'] = true;
				
				this.addEventListener('loop_count_elements_active',PAGING_PHASE2_XML);
				
				this.XML_COUNT_ELEMENTS();
			}
			else
			{
				this.STATUS.text = 'Es fehlen parameter zum laden...';
			}
		}
		
		/** =================== PAGING DATABASE ENTRIES VIA XML OVER THE NET =================== **/ 
		public function XML_COUNT_ELEMENTS():void
		{
			rpcResult = new Array();  /** reset result array of this instance **/
			HTTPSERVICE_XML = new HTTPService();
			
			HTTPSERVICE_XML.method="POST";
			HTTPSERVICE_XML.url = singleton_storage.singleton().connectionParameterss.url;
			
			HTTPSERVICE_XML.useProxy=false;
			HTTPSERVICE_XML.request['action'] = 'count';
			HTTPSERVICE_XML.resultFormat = 'object'; // xml, array, object
			
			HTTPSERVICE_XML.request = singleton_storage.singleton().connectionParameterss.endpoint_to_request(HTTPSERVICE_XML.request);
			
			if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, PAGING_PHASE2_XML);
			}
			
			if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
			{
				HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, PAGING_PHASE2_XML);
			}
			
			HTTPSERVICE_XML.send();
		}
		
		function PAGING_PHASE2_XML(event:Event = null):void
		{
			var ELEMENT_COUNT:int = undefined;
			if(event.hasOwnProperty('result'))
			{
				if(event['result'].hasOwnProperty('record'))
				{
					if(event['result']['record'].hasOwnProperty('count'))
					{
						ELEMENT_COUNT = parseInt(event['result']['record']['count'])
					}
				}
				if(event['result'].hasOwnProperty('sqlxml')) // java backend returns this
				{
					var ARRAY:Array = event['result']['sqlxml']['record']['source'];
					ELEMENT_COUNT = ARRAY[1]['COUNT(*)'];
				}
			}
			if(OBJECT_PAGING_XML['loop_count_elements_active'])
			{
				OBJECT_PAGING_XML['NUMBER_ELEMENTS'] = ELEMENT_COUNT;
				OBJECT_PAGING_XML['loop_count'] = 0;
				
				if(OBJECT_PAGING_XML['NUMBER_ELEMENTS'] > 0)
				{
					/** anteile ausrechnen, loop array bauen **/
					OBJECT_PAGING_XML['ARRAY_PAGING'] = c_MATH_inst.break_down_into_IntParts(OBJECT_PAGING_XML['NUMBER_ELEMENTS'],OBJECT_PAGING_XML['packet_size']);
					
					var FROM:int = 0;
					var TO:int = 0;
					
					OBJECT_PAGING_XML['requests'] = new Array();
					for(var counter:int = 0;!(counter == OBJECT_PAGING_XML['ARRAY_PAGING']['length']);counter++)
					{
						var NUMBER:Number = OBJECT_PAGING_XML['ARRAY_PAGING'][counter];
						TO = TO + NUMBER;
						var OBJECT:Object = {FROM:FROM,TO:TO};
						FROM = FROM + NUMBER;
						OBJECT_PAGING_XML['requests'].push(OBJECT);
					}
				}
				else
				{
					/** es sind keine anteile vorhanden, d.h. FROM / TO = 0 setzten. **/
					var FROM:int = 0;
					var TO:int = 0;
					var OBJECT:Object = {FROM:FROM,TO:TO};
					
					FROM = FROM + NUMBER;
					OBJECT_PAGING_XML['requests'].push(OBJECT);
					
					if(verbose_status)
					{
						trace(' PAGING_PHASE2_XML: COUNT_ELEMENTS REPORTED 0 ENTRIES IN TABLE! MAYBE TABLE EMPTY');
					}
				}
				
				OBJECT_PAGING_XML['paging_active'] = true;
				OBJECT_PAGING_XML['loop_count_elements_active'] = false;
			}
			
			if(OBJECT_PAGING_XML['paging_active'])
			{
				var OBJECT:Object = OBJECT_PAGING_XML['requests'][OBJECT_PAGING_XML['loop_count']];
				this.XML_READ_RANGE(singleton_storage.singleton().connectionParameterss.DatabaseName,singleton_storage.singleton().connectionParameterss.TableName,OBJECT['FROM'],OBJECT['TO']);
				OBJECT_PAGING_XML['loop_count'] = OBJECT_PAGING_XML['loop_count'] + 1;
			}
		}

		/** used method: XML
		 *  **/
		override public function XML_READ_RANGE(DatabaseName:String,TableName:String,FROM:int = undefined,TO:int = undefined):void
		{
			if(singleton_storage.singleton().connectionParameterss.TableName != null && singleton_storage.singleton().connectionParameterss.DatabaseName != null && (FROM != undefined) && (TO != undefined))
			{
				if(OBJECT_PAGING_XML['paging_active'] == false)
				{
					rpcResult = new Array();  /** reset result array of this instance **/
				}
				HTTPSERVICE_XML = new HTTPService();
				
				if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
				}
				
				if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLFault);
				}
				
				if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
				}
				
				HTTPSERVICE_XML.method="POST";
				
				HTTPSERVICE_XML.useProxy=false;
				
				var AMOUNT:int = TO - FROM;
				
				HTTPSERVICE_XML.request['action'] = "readRange";
				HTTPSERVICE_XML.request['from'] = FROM;
				HTTPSERVICE_XML.request['amount'] = AMOUNT;
				HTTPSERVICE_XML.request = singleton_storage.singleton().connectionParameterss.endpoint_to_request(HTTPSERVICE_XML.request);
				HTTPSERVICE_XML.url = singleton_storage.singleton().connectionParameterss.url;
				HTTPSERVICE_XML.send();
			}
			else
			{
				if(verbose_error)
				{
					trace('not enough parameters to execute READ_TABLE_XML');
				}
			}
		}
		
	}
}